<template>
	<view class="cropper-container">
		<canvas 
			canvas-id="cropper"
			id="cropper"
			class="cropper"
			:style="{ width: canvasWidth + 'px', height: canvasHeight + 'px' }"
			@touchstart="touchStart"
			@touchmove="touchMove"
			@touchend="touchEnd"
		></canvas>
		
		<view class="cropper-buttons">
			<button class="btn cancel" @click="cancel">取消</button>
			<button class="btn confirm" @click="confirm">确定</button>
		</view>
	</view>
</template>

<script>
	export default {
		data() {
			return {
				src: '', // 图片路径
				width: 200, // 裁剪框宽度
				height: 200, // 裁剪框高度
				fixed: true, // 是否固定比例
				ctx: null, // canvas上下文
				image: null, // 图片对象
				scale: 1, // 缩放比例
				rotate: 0, // 旋转角度
				startX: 0, // 触摸开始X坐标
				startY: 0, // 触摸开始Y坐标
				moveX: 0, // 移动X坐标
				moveY: 0, // 移动Y坐标
				isMoving: false, // 是否正在移动
				canvasWidth: 300, // canvas宽度
				canvasHeight: 300, // canvas高度
				drawWidth: 0, // 绘制宽度
				drawHeight: 0 // 绘制高度
			}
		},
		onLoad(options) {
			// 获取参数
			this.src = decodeURIComponent(options.src || '')
			this.width = parseInt(options.width || 200)
			this.height = parseInt(options.height || 200)
			this.fixed = options.fixed === 'true'
			
			// 初始化canvas
			this.initCanvas()
		},
		methods: {
			// 初始化canvas
			initCanvas() {
				// 获取canvas上下文
				this.ctx = uni.createCanvasContext('cropper', this)
				
				// 加载图片
				this.loadImage()
			},
			// 加载图片
			loadImage() {
				// 获取图片信息
				uni.getImageInfo({
					src: this.src,
					success: (res) => {
						this.image = res
						// 计算绘制尺寸
						this.calculateDrawSize()
						// 绘制图片
						this.drawImage()
					},
					fail: () => {
						uni.showToast({
							title: '加载图片失败',
							icon: 'none'
						})
					}
				})
			},
			// 计算绘制尺寸
			calculateDrawSize() {
				if (!this.image) return
				
				// 计算图片缩放比例，使图片填满画布
				const imageRatio = this.image.width / this.image.height
				const canvasRatio = this.canvasWidth / this.canvasHeight
				
				if (imageRatio > canvasRatio) {
					// 图片更宽，以高度为基准
					this.drawHeight = this.canvasHeight
					this.drawWidth = this.canvasHeight * imageRatio
				} else {
					// 图片更高，以宽度为基准
					this.drawWidth = this.canvasWidth
					this.drawHeight = this.canvasWidth / imageRatio
				}
			},
			// 绘制图片
			drawImage() {
				if (!this.ctx || !this.image) return
				
				// 清空画布
				this.ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight)
				
				// 绘制半透明背景
				this.ctx.setFillStyle('rgba(0, 0, 0, 0.5)')
				this.ctx.fillRect(0, 0, this.canvasWidth, this.canvasHeight)
				
				// 计算居中位置
				const x = (this.canvasWidth - this.drawWidth) / 2 + this.moveX
				const y = (this.canvasHeight - this.drawHeight) / 2 + this.moveY
				
				// 保存当前状态
				this.ctx.save()
				
				// 设置圆形裁剪区域
				const cropX = (this.canvasWidth - this.width) / 2
				const cropY = (this.canvasHeight - this.height) / 2
				this.ctx.beginPath()
				this.ctx.arc(cropX + this.width / 2, cropY + this.height / 2, this.width / 2, 0, Math.PI * 2, false)
				this.ctx.clip()
				
				// 移动到画布中心
				this.ctx.translate(this.canvasWidth / 2, this.canvasHeight / 2)
				
				// 旋转
				this.ctx.rotate(this.rotate * Math.PI / 180)
				
				// 缩放
				this.ctx.scale(this.scale, this.scale)
				
				// 绘制图片
				this.ctx.drawImage(
					this.src,
					-this.drawWidth / 2 + x,
					-this.drawHeight / 2 + y,
					this.drawWidth,
					this.drawHeight
				)
				
				// 恢复状态
				this.ctx.restore()
				
				// 绘制圆形边框
				this.ctx.beginPath()
				this.ctx.arc(cropX + this.width / 2, cropY + this.height / 2, this.width / 2, 0, Math.PI * 2, false)
				this.ctx.setStrokeStyle('#fff')
				this.ctx.setLineWidth(2)
				this.ctx.stroke()
				
				// 执行绘制
				this.ctx.draw()
			},
			// 触摸开始
			touchStart(e) {
				const touch = e.touches[0]
				this.startX = touch.x
				this.startY = touch.y
				this.isMoving = true
			},
			// 触摸移动
			touchMove(e) {
				if (!this.isMoving) return
				
				const touch = e.touches[0]
				const moveX = touch.x - this.startX
				const moveY = touch.y - this.startY
				
				this.moveX += moveX
				this.moveY += moveY
				
				this.startX = touch.x
				this.startY = touch.y
				
				this.drawImage()
			},
			// 触摸结束
			touchEnd() {
				this.isMoving = false
			},
			// 取消
			cancel() {
				uni.navigateBack()
			},
			// 确认
			confirm() {
				// 获取裁剪后的图片
				uni.canvasToTempFilePath({
					canvasId: 'cropper',
					x: (this.canvasWidth - this.width) / 2,
					y: (this.canvasHeight - this.height) / 2,
					width: this.width,
					height: this.height,
					destWidth: this.width * 2,
					destHeight: this.height * 2,
					fileType: 'jpg',
					quality: 1,
					success: (res) => {
						// 上传裁剪后的图片
						uni.uploadFile({
							url: 'http://localhost/dev-api/system/user/profile/avatar',
							filePath: res.tempFilePath,
							name: 'avatarfile',
							header: {
								'Authorization': uni.getStorageSync('token')
							},
							success: (uploadRes) => {
								try {
									const response = JSON.parse(uploadRes.data)
									console.log('上传响应:', response)
									if (response.code === 200) {
										// 更新头像缓存
										const userInfo = uni.getStorageSync('userInfo')
										const avatar = response.imgUrl
										uni.setStorageSync('userInfo', {
											...userInfo,
											avatar: avatar
										})
										// 发送裁剪完成事件
										uni.$emit('cropperComplete', avatar)
										uni.showToast({
											title: '上传成功',
											icon: 'success'
										})
										// 返回上一页
										uni.navigateBack()
									} else {
										uni.showToast({
											title: response.msg || '上传失败',
											icon: 'none'
										})
									}
								} catch (e) {
									console.error('上传失败:', e, uploadRes)
									console.log('响应数据:', uploadRes.data)
									uni.showToast({
										title: '上传失败',
										icon: 'none'
									})
								}
							},
							fail: (err) => {
								console.error('上传请求失败:', err)
								uni.showToast({
									title: '上传失败',
									icon: 'none'
								})
							}
						})
					},
					fail: (err) => {
						console.error('生成图片失败:', err)
						uni.showToast({
							title: '生成图片失败',
							icon: 'none'
						})
					}
				}, this)
			}
		}
	}
</script>

<style>
	.cropper-container {
		position: fixed;
		top: 0;
		left: 0;
		right: 0;
		bottom: 0;
		background-color: #000;
		display: flex;
		flex-direction: column;
		align-items: center;
		justify-content: center;
	}
	
	.cropper {
		background-color: transparent;
	}
	
	.cropper-buttons {
		position: fixed;
		left: 0;
		right: 0;
		bottom: 0;
		height: 100rpx;
		display: flex;
		align-items: center;
		justify-content: space-around;
		background-color: rgba(0, 0, 0, 0.5);
	}
	
	.btn {
		width: 200rpx;
		height: 80rpx;
		line-height: 80rpx;
		text-align: center;
		border-radius: 40rpx;
		font-size: 28rpx;
	}
	
	.cancel {
		background-color: #666;
		color: #fff;
	}
	
	.confirm {
		background-color: #409EFF;
		color: #fff;
	}
</style> 